//
// Created by jingjia on 10/15/21.
//

#include "os_bsd.hpp"
#include "../../../share/vm/runtime/os.hpp"
#include "../../../share/vm/runtime/thread.hpp"
#include "../../../share/vm/runtime/mutexLocker.h"

// thread stack

#define K 1024

static size_t min_stack_allowed = 64 * K;

static void* java_start(Thread* thread) {
    OSThread* osThread = thread->osThread();
    osThread->setThreadId(getpid());

    {
        Monitor* monitor = osThread->startThreadLock();
        //get lock
        //monitor->lock();

        MutexLockerEx mutexLockerEx(monitor);
        //set thread state
        osThread->setThreadState(ThreadState::INITIALIZED);
        //notify the parent thread
        INFO_PRINT("threadState: INITIALIZED\n");

        monitor->notify(); //虽然notify，但是临界区的lock锁并未释放，临界区资源还是不能访问

        while (osThread->threadState() == ThreadState::INITIALIZED) {
            monitor->wait();
        }
    }

    assert(osThread->threadState() == ThreadState::RUNNABLE, "thread status is not runnable");

    thread->run();
}

void OS::create_thread(Thread *_thread, ThreadType threadType, size_t stack_size) {

    //init
    OSThread* osThread = new OSThread();
    osThread->setThreadState(ThreadState::ALLOCATED);
    INFO_PRINT("threadState: ALLOCATED\n");
    _thread->setOsThread(osThread);

    pthread_t pthread;
    pthread_attr_t attr;
    pthread_attr_init(&attr);

    int stackSize = stack_size < min_stack_allowed ? min_stack_allowed : stack_size;
    //set stack size
    pthread_attr_setstacksize(&attr, stackSize);

    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    pthread_create(&pthread, &attr, reinterpret_cast<void *(*)(void *)>(java_start), _thread);
    pthread_attr_destroy(&attr);

    Monitor* monitor = osThread->startThreadLock();
    {
        MutexLockerEx mutexLockerEx(monitor);
        while(osThread->threadState() == ThreadState::ALLOCATED) {
            monitor->wait();
        }
    }
}